package com.xunyin.utils;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.xunyin.cache.TtlockBean;
import com.xunyin.cache.TtlockCache;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * 通通锁-调用接口相关
 */
@Slf4j
public class RequestTtlockUtils {

    private static final MediaType CONTENT_TYPE = MediaType.parse("application/x-www-form-urlencoded");

    private static final Gson gson = new Gson();

    // 开发者clientId
    private static String clientId = "cc78bf34ca7f4c398714c64e3cd660b1";
    // 开发者clientSecret
    private static String clientSecret = "a03e6eeb158327e4243053608baea8bb";
    // 通通锁APP注册账号
    private static String username = "550753187@qq.com";
    // 通通锁APP登录密码需md5加密
    private static String password = "aa2658ac0984bc146d78f8b7215d8094";

    private static String lockId = "15739879";

    // 获取 http client
    private static OkHttpClient getHttpClient() {
        OkHttpClient client = new OkHttpClient();
        //client.connectTimeoutMillis(connTimeout, TimeUnit.SECONDS);
        //client.setReadTimeout(readTimeout, TimeUnit.SECONDS);
        //client.setWriteTimeout(writeTimeout, TimeUnit.SECONDS);

        return client;
    }

    /**
     * 生成header
     *
     */
    public static Headers getHeader() throws Exception {
        Headers.Builder hb = new Headers.Builder();
        hb.add("Content-Type", "application/x-www-form-urlencoded");
        return hb.build();
    }

    /**
     * 获取通通锁的开门token
     * @param lockId
     * @return
     * @throws Exception
     */
    public static TtlockBean getTtlockToken(String lockId) throws Exception {
        //TtlockBean tlockBean = null;
        TtlockBean tlockBean = (TtlockBean)TtlockCache.getAccessTokenCache(lockId);

        if(tlockBean!=null){

            Date endDate = tlockBean.getEndDate();
            long now = (new Date()).getTime();
            long endTime = endDate.getTime();
            long timeDiff = (endTime - now) / 1000 / 60;

            log.info("now:"+now);
            log.info("endTime:"+endTime);
            log.info("timeDiff:"+timeDiff);
            log.info("endDate:"+DateUtils.parseDate2String(endDate, "yyyy-MM-dd HH:mm:ss"));

            if (timeDiff < 0) {

                // 刷新token
                log.info("刷新token");
                // refreshSession(storeId);
                Object result = executeToken(clientId,clientSecret,username,password);
                String res = gson.toJson(result);
                log.info("getTtlockToken-res:"+res);
                JSONObject resJson = JSONObject.parseObject(res);
                String accessToken = resJson.getString("access_token");
                Long expiresIn = resJson.getLongValue("expires_in");
                endDate = DateUtil.addDate(new Date(), Calendar.SECOND, expiresIn.intValue());
                tlockBean.setAccessToken(accessToken);
                tlockBean.setEndDate(endDate);
                tlockBean.setExpiresIn(expiresIn);
                TtlockCache.setAccessTokenCache(lockId,tlockBean);

            }

            return tlockBean;

        }else{

            Object result = executeToken(clientId,clientSecret,username,password);
            String res = gson.toJson(result);
            log.info("getTtlockToken-res:"+res);
            JSONObject resJson = JSONObject.parseObject(res);
            String accessToken = resJson.getString("access_token");
            Long expiresIn = resJson.getLongValue("expires_in");
            Date endDate = DateUtil.addDate(new Date(), Calendar.SECOND, expiresIn.intValue());
            tlockBean = new TtlockBean();
            tlockBean.setAccessToken(accessToken);
            tlockBean.setEndDate(endDate);
            tlockBean.setExpiresIn(expiresIn);
            TtlockCache.setAccessTokenCache(lockId,tlockBean);
            return tlockBean;

        }

/*        Object result = executeToken(clientId,clientSecret,username,password);
        String res = gson.toJson(result);
        log.info("getTtlockToken-res:"+res);
        JSONObject resJson = JSONObject.parseObject(res);
        String accessToken = resJson.getString("access_token");
        Long expiresIn = resJson.getLongValue("expires_in");
        Date endDate = DateUtil.addDate(new Date(), Calendar.SECOND, expiresIn.intValue());
        tlockBean = new TtlockBean();
        tlockBean.setAccessToken(accessToken);
        tlockBean.setEndDate(endDate);
        tlockBean.setExpiresIn(expiresIn);
        TtlockCache.setAccessTokenCache(lockId,tlockBean);
        return tlockBean;*/


    }


    /**
     * 远程开锁
     * @param lockId
     * @return
     */
    public static Boolean executeUnlock(String lockId) throws Exception {
        TtlockBean tlockBean = getTtlockToken(lockId);
        //return executeUnlock(clientId,tlockBean.getAccessToken(),lockId);
        Object unlockResult = executeUnlock(clientId,tlockBean.getAccessToken(),lockId);
        String resUnlock = gson.toJson(unlockResult);
        log.info("resUnlock:"+resUnlock);
        JSONObject resJson = JSONObject.parseObject(resUnlock);
        Integer errcode = resJson.getInteger("errcode");
        if(errcode == 0){
            return true;
        }else{
            return false;
        }
    }


    public static Object executeToken(String clientId,String clientSecret,String username,String password) throws Exception {

        // 发送POST请求（Form表单）
        String formUrl = "https://cnapi.sciener.com/oauth2/token";
        FormBody.Builder formBuilder = new FormBody.Builder()
                .add("clientId", clientId)
                .add("clientSecret", clientSecret)
                .add("username",username)
                .add("password",password);
        String formResponse = "";
        try {
            formResponse = doPostRequest(formUrl, formBuilder.build());
            //System.out.println("Form POST Response: " + formResponse);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return gson.fromJson(formResponse, Object.class);
    }



    /**
     * 远程开锁
     * @param clientId
     * @param accessToken
     * @param lockId
     * @return
     */
    public static Object executeUnlock(String clientId,String accessToken,String lockId){

        //  String accessToken = TokenCache.getAccessTokenCache(tuyaClientId);

        String formUrl = "https://cnapi.sciener.com/v3/lock/unlock";
        String timestamp = String.valueOf(System.currentTimeMillis());
        FormBody.Builder formBuilder = new FormBody.Builder()
                .add("clientId", clientId)
                .add("accessToken", accessToken)
                .add("lockId",lockId)
                .add("date",timestamp);

        String formResponse = "";

        try {
            log.info("executeUnlock-clientId:"+clientId);
            log.info("executeUnlock-accessToken:"+accessToken);
            log.info("executeUnlock-lockId:"+lockId);
            log.info("executeUnlock-timestamp:"+timestamp);
            formResponse = doPostRequest(formUrl, formBuilder.build());
            log.info("executeUnlock-formResponse:"+formResponse);
            // System.out.println("Form POST Response: " + formResponse);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return gson.fromJson(formResponse, Object.class);
    }

    public static void main(String[] args) throws Exception {

/*        String clientId = "9a24ea6fe89a41d6bfbd1da17bb7287c";
        String clientSecret = "81353e59cbd034a2ac0fce1122ea5e2a";
        String lockId =  "10732491";
        Object result = executeToken(clientId,clientSecret,"3594419785@qq.com","f44b6e62b8125b157c879e63c28ad52c");
        String res = gson.toJson(result);
        System.out.println(res);
        JSONObject resJson = JSONObject.parseObject(res);
        String accessToken = resJson.getString("access_token");*/

        // expires_in

        // accessToken


        // 远程开锁
/*        Object unlockResult = executeUnlock(clientId,accessToken,lockId);
        String resUnlock = gson.toJson(unlockResult);
        System.out.println(resUnlock);*/



    }

    public static Object executeKeyboardPwd(
            String clientId,
            String accessToken,
            String lockId,
            String keyboardPwdType,String startDate,String endDate,String date){

        String formUrl = "https://cnapi.ttlock.com/v3/keyboardPwd/get";
        FormBody.Builder formBuilder = new FormBody.Builder()
                .add("clientId", clientId)
                .add("accessToken", accessToken)
                .add("lockId",lockId)
                .add("keyboardPwdType",keyboardPwdType)
                .add("startDate",startDate)
                .add("endDate",endDate)
                .add("date",date);
        String formResponse = "";
        try {
            formResponse = doPostRequest(formUrl, formBuilder.build());
            System.out.println("Form POST Response: " + formResponse);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return gson.fromJson(formResponse, Object.class);
    }



    public static String doPostRequest(String url, RequestBody requestBody) throws IOException {
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        OkHttpClient client = new OkHttpClient();
        try (Response response = client.newCall(request).execute()) {
            return response.body().string();
        }
    }


    //private static final OkHttpClient client = new OkHttpClient();

    public static String doPostRequest(String url, String jsonBody) throws IOException {
        RequestBody body = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=utf-8"), jsonBody);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        OkHttpClient client = new OkHttpClient();
        try (Response response = client.newCall(request).execute()) {
            return response.body().string();
        }
    }

    /**
     * 执行请求
     */
    public static Response doRequest(Request request) {
        Response response;
        try {
            response = getHttpClient().newCall(request).execute();
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage());
        }
        return response;
    }

    public static String getPathAndSortParam(URL url) {
        try {
            // supported the query contains zh-Han char
            String query = URLDecoder.decode(url.getQuery(), "UTF-8");
            String path = url.getPath();
            if (StringUtils.isBlank(query)) {
                return path;
            }
            Map<String, String> kvMap = new TreeMap<>();
            String[] kvs = query.split("\\&");
            for (String kv : kvs) {
                String[] kvArr = kv.split("=");
                if (kvArr.length > 1) {
                    kvMap.put(kvArr[0], kvArr[1]);
                } else {
                    kvMap.put(kvArr[0], "");
                }
            }
            return path + "?" + kvMap.entrySet().stream().map(it -> it.getKey() + "=" + it.getValue())
                    .collect(Collectors.joining("&"));
        } catch (Exception e) {
            return url.getPath();
        }
    }







    /**
     * 处理post请求
     */
    public static Request.Builder postRequest(String url, String body) {
        Request.Builder request;
        try {
            request = new Request.Builder()
                    .url(url)
                    .post(RequestBody.create(CONTENT_TYPE, body));
        } catch (IllegalArgumentException e) {
            throw new RuntimeException(e.getMessage());
        }
        return request;
    }



}
